-- ********************************************
-- * Copyright (c) 2012 TPV R&D Center Brazil *
-- * All Rights Reserved                      *
-- ********************************************

--- toolkit.component.List

local List = Box:new()

function List:new(o)
   if (type(o) ~= 'table') then
      o = {}
   end

   local newList = Box:new(o)

   newList.parent = nil

   newList.componentType = "ListHUB"

   newList.fullData = {}
   newList.data = {}
   newList.boxFocus = nil

   newList.page = {
      intervalLeft = o.intervalLeft or 0,
      intervalTop = o.intervalTop or 0,
      updateFocused = false,
      hideScroll = false,
      lineSize = 1,
      linePosition = 1,
      columnSize = 1,
      columnPosition = 1
	}

   newList.nav = {
      selLine = 0,
      curLine = 1,
      lineLimit = 1,
      selColumn = 0,
      curColumn = 1,
      columnLimit = 1,
   }

   newList.scroll = {
      width = 6,
      color = {255, 255, 255, 200}
   }

   newList.scrollContent = nil
   newList.focusContent = nil
   newList.lastFocusContent = nil
   newList.listContent = nil
   newList.cacheContent = {}
   newList.pages = 1
   newList.currentPage = 1

   newList.editMode = false
   newList.editContent = nil

   newList.updateMode = {
      total = 1,
      partial = 2,
   }


   --generate an object
   setmetatable(newList, self)
   self.__index = self

   return newList
end

function List:setActive(bEnabled, bAvoidFlush)
   if (type(bEnabled) == 'boolean') then

      if (bEnabled ~= self.isActivated) then
         self.isActivated = bEnabled
         --update list
         self.parent:composeFocusContentHUB(self)
         self.parent:updateListHUB(self, true, true, bAvoidFlush)
      end
   end
end

function List:redraw(bAvoidFlush)
   self.parent:updateListHUB(self, true, true, bAvoidFlush)
end

function List:getFocused()
   local index = ((self.nav.curLine - 1) * self.nav.columnLimit) + (self.nav.curColumn - 1) + 1
   return self.data[index]
end

function List:getCurrentPosition()
   return self.nav.curLine, self.nav.curColumn
end

function List:setFocused(nLine, nColumn)
   --set current line and column
   if (nLine > 0 and nLine <= self.nav.lineLimit) and
      (nColumn > 0 and nColumn <= self.nav.columnLimit) then
      self.nav.curLine = nLine
      self.nav.curColumn = nColumn
   end
end

function List:setSelected(nLine, nColumn)
   --set selected line and column
   if (#self.nav.columnLimit > 0) then
      if (nLine > 0 and nLine <= self.nav.lineLimit) and
         (nColumn > 0 and nColumn <= self.nav.columnLimit[nLine]) then
         self.nav.selLine = nLine
         self.nav.curLine = nLine
         self.nav.selColumn = nColumn
         self.nav.curColumn = nColumn
      end
   end
end

function List:setPage(o)
   if (type(o) == 'table') then
      self.page.lineSize = o.lineSize or self.page.lineSize
      self.page.columnSize = o.columnSize or self.page.columnSize
      self.page.updateFocused = o.updateFocused or self.page.updateFocused
      self.page.hideScroll = o.hideScroll or self.page.hideScroll
   end
end

function List:setData(o)
   if (type(o) == 'table') then
      self.dataIndex = o
   end
end

function List:addFocus(boxFocus)
   self.boxFocus = boxFocus or Box:new()
end

function List:replaceFocus(boxFocus)
   self.lastFocusContent = canvas:new(self.focusContent:attrSize())
   self.lastFocusContent:attrColor(0, 0, 0, 0)
   self.lastFocusContent:clear()
   self.lastFocusContent:compose(0, 0, self.focusContent)

   self.boxFocus = boxFocus or Box:new()

   self.parent:composeFocusContentHUB(self)
   self.parent:updateListHUB(self, true)
end

function List:enableEditMode(enable)
   self.editMode = enable

   if (self.editMode) then
      self.parent:composeEditFocusContentHUB(self)
      self.parent:updateListHUB(self, true)
   else
      self.editContent = nil
   end
end

function List:addList(boxElement, tData)
   --set data
   if (type(tData) == 'table') then
      self.fullData = tData
      self.pages = #self.fullData

      self.data = self.fullData[self.currentPage]

      self.nav.lineLimit = self.page.lineSize
      self.nav.columnLimit = self.page.columnSize

   end
   --set elements
   if (type(boxElement) == 'table') then
      if (boxElement.componentType == "Box") then
         self.children = boxElement
      end
   end
end

function List:moveUp()
   if (self.nav.lineLimit <= 1) then
      --do nothing
      return
   end

   --remove focus
   self.parent:updateListHUB(self, false)

   --check if first line
   if (self.nav.curLine == 1) then
      return
      --self.nav.curLine = self.nav.lineLimit
   else
      self.nav.curLine = self.nav.curLine - 1
   end

   --update list
   self.parent:updateListHUB(self, true, false)
end

function List:moveDown()
   if (self.nav.lineLimit <= 1) then
      --do nothing
      return
   end

   --remove focus
   self.parent:updateListHUB(self, false)

   --check if last line
   if (self.nav.curLine == self.nav.lineLimit) then
      return
      --self.nav.curLine = 1
   else
      if (self.nav.curColumn + 5 <= #self.data) then
         self.nav.curLine = self.nav.curLine + 1
      elseif (#self.data > 5) then
         self.nav.curLine = self.nav.curLine + 1
         self.nav.curColumn = #self.data - 5
      end
   end

   --update list
   self.parent:updateListHUB(self, true, false)
end

function List:moveLeft()
   if (self.nav.columnLimit <= 1) then
      --do nothing
      return
   end

   local bUpdateMode = nil

   --remove focus
   self.parent:updateListHUB(self, false)

   --check if first column
   if ((self.nav.curColumn - 1) < 1) then
      if (self.currentPage > 1) then
         self.currentPage = self.currentPage - 1
      else
         self.currentPage = self.pages
      end

      self.data = self.fullData[self.currentPage]

      local nextPos = ((self.nav.curLine - 1) * self.nav.columnLimit) + (self.nav.curColumn - 1) + 1
      if (nextPos > #self.data) then
         self.nav.curLine = 1
      end

      bUpdateMode = self.updateMode.total
   else
      self.nav.curColumn = self.nav.curColumn - 1
   end

   --update list
   self.parent:updateListHUB(self, true, bUpdateMode)
end

function List:moveRight()
   if (self.nav.columnLimit <= 1) then
      --do nothing
      return
   end

   local bUpdateMode = nil

   --remove focus
   self.parent:updateListHUB(self, false)

   --check if last column
   if ((self.nav.curColumn + 1) > self.nav.columnLimit) then
      if (self.currentPage < self.pages) then
         self.currentPage = self.currentPage + 1
      else
         self.currentPage = 1
      end

      self.data = self.fullData[self.currentPage]

      local nextPos = ((self.nav.curLine - 1) * self.nav.columnLimit) + (self.nav.curColumn - 1) + 1
      if (nextPos > #self.data) then
         if (#self.data > 5 and #self.data < 10) then
            self.nav.curLine = 1
            self.nav.curColumn = self.nav.columnLimit
         else
            self.nav.curLine = 1
            self.nav.curColumn = #self.data
         end
      end

      --self.nav.curColumn = 1
      bUpdateMode = self.updateMode.total
   else
      local nextPos = ((self.nav.curLine - 1) * self.nav.columnLimit) + (self.nav.curColumn - 1 + 1) + 1

      if (nextPos <= #self.data) then
         self.nav.curColumn = self.nav.curColumn + 1
      elseif (self.nav.curLine == 2) then
         self.nav.curLine = 1
         self.nav.curColumn = self.nav.columnLimit
      else
         self.currentPage = 1
         self.nav.curColumn = self.nav.columnLimit
         self.data = self.fullData[self.currentPage]
         bUpdateMode = self.updateMode.total
      end
   end

   --update list
   self.parent:updateListHUB(self, true, bUpdateMode)
end

function List:dispose()
   self.scrollContent = nil
   self.focusContent = nil
   self.listContent = nil
   self.firstContent = nil
   self.lastContent = nil
   collectgarbage()
end

return List
